/*
    kOTF Open Trace Format - a library for generating execution traces.
    Copyright 2012 Daniel K. O.

    kOTF is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    kOTF is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with kOTF.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef KOTF_READER_H
#define KOTF_READER_H

#include <fstream>
#include <map>
#include <iterator>

#include <kotf/Types.hpp>

#include <boost/ptr_container/ptr_map.hpp>

#include <kotf/Records.hpp>
#include <kotf/Events.hpp>
#include <kotf/Error.hpp>

namespace kotf {
    
    class StreamReader;

    /** \brief class that reads a kOTF session.

        The constructor takes a path (with or without the .kotf extension) to a
        session file. It contains maps from ids to names for each record type.

        It also provides a ptr_map of streams which can be iterated over.
     */

    class SessionReader {
    public:
        
        string name;
        uint64_t startTime, finishTime;

        boost::ptr_map<uint64_t, StreamReader> streams;
        typedef boost::ptr_map<uint64_t, StreamReader>::iterator iterator;
        typedef boost::ptr_map<uint64_t, StreamReader>::const_iterator const_iterator;

        std::map<uint64_t, std::string> states, counters, channels;

        SessionReader(const std::string& sessname);
    };


    /** \brief class that reads a stream file

        The events are accessed with a random-access iterator (which is implemented with mmap)
        of type const Event*. The events are guaranteed to be ordered by timestamp so
        it is possible to perform binary searches.
     */
    class StreamReader {
    public:
        const string name;

    private:
        // RAII wrapper for mmap
        class MMapFile {
            int fd;
            uint64_t fsize;
            void * ptr;
        public:


            MMapFile(const string& fname) throw (OpenError, MmapError);
            ~MMapFile();
            
            size_t size() const;
            template<class T>
            const T* as() const 
            {
                return reinterpret_cast<const T*>(ptr);
            }
        };
        MMapFile file;

    public:

        typedef Event* iterator;
        typedef const Event* const_iterator;

        StreamReader(const string& sessname, const string& n) throw(InvalidStream);
        
        size_t size() const;

        const_iterator begin() const;
        const_iterator end() const;
    };

}


#endif
